package org.ielts.service.security;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.ielts.domain.base.Campus;
import org.ielts.domain.base.Department;
import org.ielts.domain.security.Role;
import org.ielts.domain.security.User;
import org.ielts.repository.security.DepartmentRepository;
import org.ielts.repository.security.UserRepository;
import org.ielts.repository.security.UserRoleRepository;
import org.ielts.util.MapListWapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.yifeng.crypto.BytesBox;
import com.yifeng.crypto.CryptoUtils;
import com.yifeng.security.authentication.TokenAuthentication;
import com.yifeng.security.users.User.Status;

@Service
public class UserService {

	private boolean encryptPwd = true;
	private String initPwd = "123456";

	@Autowired
	UserRepository userRepository;

	@Transactional
	public Page<User> listUser(String name, Pageable pageable) {
		Page<User> users = userRepository.findAll(name, pageable);

		return users;
	}

	@Transactional
	public User createUser(String name, String title, String[] roleIds) {
		User user = new User();
		user.setName(name);
		user.setTitle(title);
		user.setCreateTime(new Date());

		String pwd = initPwd;
		String encryptedPwd = pwd;
		if (encryptPwd) {
			encryptedPwd = CryptoUtils.MD5().digest(BytesBox.decode(pwd)).toHexString();
		}
		user.setPassword(encryptedPwd);

		userRepository.save(user);

		for (int i = 0; i < roleIds.length; i++) {
			String roleId = roleIds[i];
			Role role = new Role();
			role.setId(roleId);

			userRoleRepository.addUserInRole(user, role);
		}

		return user;
	}

	@Autowired
	UserRoleRepository userRoleRepository;

	@Transactional
	public void removeUser(String id) {
		userRepository.delete(id);
	}

	@Transactional
	public User findUser(String id) {
		return userRepository.findOne(id);
	}

	@Transactional
	public User findByName(String name) {
		User user = userRepository.findOneByName(name);

		return user;
	}

	@Transactional
	public void modifyUser(String id, String name, String title, String[] roleIds) {
		User user = userRepository.findOne(id);
		user.setName(name);
		user.setTitle(title);

		user.getRoles().clear();
		for (String roleId : roleIds) {
			Role role = new Role();
			role.setId(roleId);

			userRoleRepository.addUserInRole(user, role);
		}
	}

	@Transactional
	public Status checkUserStatus(String loginName, String pwd) {
		User user = userRepository.findByLoginName(loginName);
		if (user == null) {
			return Status.NotExists;
		}
		String encryptedPwd = pwd;
		if (encryptPwd) {
			encryptedPwd = CryptoUtils.MD5().digest(BytesBox.decode(pwd)).toHexString();
		}

		user = userRepository.findUserByLoginNameAndPassword(loginName, encryptedPwd);
		if (user == null) {
			return Status.PasswordError;
		}

		return Status.Success;
	}

	@Transactional
	public void resetPassword(String id) {
		User user = userRepository.findOne(id);
		String encryptedPwd = initPwd;
		if (encryptPwd) {
			encryptedPwd = CryptoUtils.MD5().digest(BytesBox.decode(initPwd)).toHexString();
		}

		user.setPassword(encryptedPwd);
	}

	public boolean isEncryptPwd() {
		return encryptPwd;
	}

	public void setEncryptPwd(boolean encryptPwd) {
		this.encryptPwd = encryptPwd;
	}

	public String getInitPwd() {
		return initPwd;
	}

	public void setInitPwd(String initPwd) {
		this.initPwd = initPwd;
	}

	@Transactional
	public void changePwd(String id, String pwd) {
		User user = userRepository.findOne(id);
		String encryptedPwd = pwd;
		if (encryptPwd) {
			encryptedPwd = CryptoUtils.MD5().digest(BytesBox.decode(pwd)).toHexString();
		}

		user.setPassword(encryptedPwd);
	}

	@Autowired
	DepartmentRepository departmentRepository;

	@Transactional
	public User createUser(String loginName, String name, String title, String[] roleIds, String departmentId,
			String campusId, String no, Date entryTime) {
		User user = new User();
		user.setLoginName(loginName);
		user.setName(name);
		user.setTitle(title);
		user.setCreateTime(new Date());

		Campus campus = new Campus();
		campus.setId(campusId);

		user.setCampus(campus);
		user.setNo(no);
		user.setEntryTime(entryTime);

		Department department = departmentRepository.findOne(departmentId);

		user.setDepartment(department);

		String pwd = initPwd;
		String encryptedPwd = pwd;
		if (encryptPwd) {
			encryptedPwd = CryptoUtils.MD5().digest(BytesBox.decode(pwd)).toHexString();
		}
		user.setPassword(encryptedPwd);

		userRepository.save(user);

		for (int i = 0; i < roleIds.length; i++) {
			String roleId = roleIds[i];
			Role role = new Role();
			role.setId(roleId);

			userRoleRepository.addUserInRole(user, role);
		}

		return user;
	}

	@Transactional
	public User modifyUser(String id, String loginName, String name, String title, String campusId, String no,
			String[] roleIds, String departmentId, Date entryTime) {
		User user = userRepository.findOne(id);
		user.setName(name);
		user.setLoginName(loginName);
		user.setTitle(title);

		Campus campus = new Campus();
		campus.setId(campusId);

		user.setCampus(campus);

		Department department = new Department();
		department.setId(departmentId);
		user.setDepartment(department);

		user.setEntryTime(entryTime);
		user.setNo(no);

		user.getRoles().clear();
		for (String roleId : roleIds) {
			Role role = new Role();
			role.setId(roleId);

			userRoleRepository.addUserInRole(user, role);
		}

		return user;
	}

	public void setUserCampus(String campus) {
		// TODO Auto-generated method stub

	}

	@Transactional
	public User findByLoginName(String loginName) {
		User user = userRepository.findByLoginName(loginName);

		return user;
	}

	@Transactional
	public MapListWapper<String, User> findNameIdMapMatchRoleName(String roleName_like) {
		Map<String, User> map = new HashMap<String, User>();

		Iterable<User> us = userRepository.findByRoleNameLike(roleName_like);
		for (User u : us) {
			map.put(u.getName().toLowerCase(), u);
		}
		MapListWapper<String, User> result = new MapListWapper<String, User>(map, us);
		return result;
	}
}
